package com.ironman.analyze.core.compute;

import com.ironman.analyze.core.compute.base.BaseComputer;
import com.ironman.analyze.core.compute.base.BaseVectorComputer;
import com.ironman.analyze.core.compute.entity.HeadingWindowData;
import com.ironman.analyze.core.context.TrainingContext;
import com.ironman.analyze.core.handler.HeadingPostHandler;
import com.ironman.common.entity.HeadingData;
import com.ironman.common.params.HeadingParam;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

/**
 * 航向计算
 */
@Slf4j
public class HeadingVectorComputer extends BaseVectorComputer<HeadingData> implements BaseComputer<HeadingData, HeadingWindowData> {

    private final HeadingPostHandler headingPostHandler;

    public HeadingVectorComputer(TrainingContext trainingContext, HeadingParam headingParam) {
        super(headingParam.getWindowSize(), trainingContext);
        this.headingPostHandler = new HeadingPostHandler(headingParam);
    }

    @Override
    public void computeWindowData(List<HeadingData> dataList) {
        for (HeadingData headingData : dataList) {
            windowData(headingData, new BiConsumer<Date, Double>() {
                @Override
                public void accept(Date ts, Double headingT) {
                    Double headingM = null;
                    if (Objects.nonNull(headingT)) {
                        Float declination = headingData.getDeclination();
                        headingM = Objects.nonNull(declination) ? headingT - declination : null;
                        if (Objects.nonNull(headingM)) {
                            headingM %= 360;
                        }
                    }
                    HeadingWindowData headingWindowData = new HeadingWindowData(ts, headingT, headingM);
                    headingPostHandler.handler(headingWindowData, new Consumer<HeadingWindowData>() {
                        @Override
                        public void accept(HeadingWindowData headingWindowData) {
                            syncData(headingWindowData);
                        }
                    });
                }
            });
        }
    }

    @Override
    public void syncData(HeadingWindowData windowData) {
        getTrainingContext().getHeadingWindowDataMap().put(windowData.getTs(), windowData);
    }
}
